#ifndef _CLISTBOX_H_
#define _CLISTBOX_H_

#include <buola/utility/usignal.h>
#include <buola/utility/uevent.h>

#include <buola/gui/cwindow.h>
#include <buola/widgets/clistwidget.h>
#include <buola/gui/dnd/cdroptarget.h>
#include <buola/gui/dnd/cdragsource.h>
#include <buola/image/cfont.h>

namespace buola { namespace gui {

class CLBRenderer;

class CListBox : public CListWidget,public CDropTarget,
                 public CDragSource
{
public:
    enum
    {
        //renderers
        STYLE_ARRAY=        0x00000100,
        STYLE_LIST=         0x00000200,
        STYLE_DETAIL=       0x00000300,
        STYLE_CHECKBOXES=   0x00000400,
        STYLE_GROUPTREE=    0x00000500,
        STYLE_STRIP=        0x00000600,
        STYLE_RENDERER=     0x00000f00,
        //view style
        STYLE_NOICON=       0x00001000,
        STYLE_NOTEXT=       0x00002000,
        STYLE_SINGLECOLUMN= 0x00004000,
        STYLE_HORIZONTAL=   0x00004000,
        STYLE_FREEMOVE=     0x00008000,
        STYLE_NORULER=      0x00010000,
        STYLE_MULTILINE=    0x00020000,
        STYLE_ALIGNCENTER=  0x00040000,
        STYLE_ALIGNRIGHT=   0x00080000,
        STYLE_GROUPS=       0x00100000,
        STYLE_INVERTTEXT=   0x00200000,
        STYLE_VIEW=         0x003fff00,
        //function style
        STYLE_DRAGNDROP=    0x00400000,
        STYLE_EDITABLE=     0x00800000,
        //selection style
        STYLE_SINGLE=       0x00000000,
        STYLE_MULTIPLE=     0x01000000,
        STYLE_TOGGLE=       0x02000000,
        STYLE_ONECLICK=     0x04000000,
        STYLE_SELECTION=    0x07000000,
        //menu style
        STYLE_ICONMENU=     0x10000000,
        STYLE_VIEWMENU=     0x20000000,
        STYLE_USERMENU=     0x40000000,
        STYLE_MENU=         0x70000000,

        //default styles
        STYLE_DEFAULTVIEW=  STYLE_ARRAY|STYLE_MULTILINE|STYLE_ALIGNCENTER|
                            STYLE_ICONMENU|STYLE_VIEWMENU|STYLE_EDITABLE,
        STYLE_ARRAYVIEW=    STYLE_ARRAY|STYLE_MULTILINE|STYLE_ALIGNCENTER,
        STYLE_DETAILVIEW=   STYLE_DETAIL,
        STYLE_LISTVIEW=     STYLE_LIST,
        STYLE_SIMPLEVIEW=   STYLE_LIST|STYLE_NOICON,
        STYLE_SINGLEVIEW=   STYLE_ARRAY|STYLE_SINGLECOLUMN|STYLE_ALIGNCENTER,
        STYLE_CHECKVIEW=    STYLE_CHECKBOXES|STYLE_MULTIPLE|STYLE_TOGGLE,
        STYLE_GROUPVIEW=    STYLE_GROUPTREE,
        STYLE_STRIPVIEW=    STYLE_STRIP|STYLE_NOTEXT|STYLE_HORIZONTAL
    };

public:
    CListBox();
    CListBox(CListWidget*);
    virtual ~CListBox();

public:
    void EnsureVisible(SItem*,bool pMore);

    void SetFont(img::PFont pFont);
    img::PFont GetFont() {   return mFont;   }

    int GetIconSize()           {   return mIconSize;   }
    void SetIconSize(int);

    CSize_i GetImageSize()         {   return mImageSize;  }
    void SetImageSize(const CSize_i&);

    bool GetAutoUpdate()        {   return mAutoUpdate; }
    void SetAutoUpdate(bool);
    void Update();

    const PScrollBar &GetVScroll()    {   return mVScroll;    }
    const PScrollBar &GetHScroll()    {   return mHScroll;    }

    void SetMargins(const CRect_d &pMargins);
    const CRect_d &GetMargins()   {   return mMargins;    }
    const CPoint_d &GetScrollPos()  {   return mScrollPos;  }

    CSize_d GetMaxImageSize();

    void StartEditing(SItem *pItem);
    void EndEditing();

    void CreateRenderer();

    void AdjustHeight();

protected:
////////////// Event handling //////////////
    virtual void OnExpose(const CExposeEvent &pE);
    void OnHScroll(int pPos);
    void OnVScroll(int pPos);
    virtual void OnButtonDown(const CMouseEvent &pE);
    virtual void OnButtonUp(const CMouseEvent &pE);
    virtual void OnMouseMove(const CMouseEvent &pE);
    virtual void OnMouseWheel(const CMouseEvent &pE);
    virtual void OnSize(const CGeometryEvent &pE);

    virtual void OnFocusIn(const CFocusEvent &pE);
    virtual void OnFocusOut(const CFocusEvent &pE);

    virtual void OnStyleChanged(TStyle);

    virtual void OnItemChanged(SItem*);
    virtual void OnItemAdded(SItem*);
    virtual void OnItemRemoved(SItem*);
    virtual void OnItemSelected(SItem*);
    virtual void OnItemDblClk(SItem*);
    virtual void OnLWFieldsChanged();
    virtual void OnLWBigChange();

    virtual void OnFillMenu(PMenu,bool) {}

    virtual void OnDragDrag(CDrag*,CClipboard*);

    virtual void OnDropEnter(CDrop*,const CPoint_d&);
    virtual void OnDropDrop(CDrop*,const CPoint_d&,EDNDActions);

public:
    USignal<void(PMenu,bool)> sFillMenu;
    USignal<void(CDrop*,const CPoint_d&)> sDrop;
    UEvent<void(SItem*,TID)> eEdited;
    UEvent<void(SItem*,TID)> sSelected;
    UEvent<void(SItem*,TID)> sUnselected;
    UEvent<void(SItem*,TID)> eDblClick;


protected:
/////////////// internal data //////////////
    img::PFont mFont;

    PScrollBar mHScroll;
    PScrollBar mVScroll;

    bool mDragging;
    bool mSelecting;
    SItem *mEditing;

    CPoint_d mDragPoint;
    CPoint_d mLastDragPoint;

    int mIconSize;
    CSize_i mImageSize;

    bool mAutoUpdate;
    PEditBox mEditBox;

    CRect_d mMargins;

    CLBRenderer *mRenderer;

    CPoint_d mScrollPos;
    
    friend class CLBArrayRenderer;
    friend class CLBListRenderer;
    friend class CLBDetailRenderer;
    friend class CLBCheckRenderer;
    friend class CLBGroupRenderer;
    friend class CLBStripRenderer;
};

/*namespace gui*/ } /*namespace buola*/ }

#endif
